#include <cctype>
#include <string>
#include <stack>
#include <unordered_map>
#include <algorithm>
#include <functional>

#include <iostream>

class Expression
{
public:
   Expression(const std::string& expression)
      :_expression(expression)
   {
      // std::cout << "expression str in constructor: " << _expression << std::endl; // for debug
   }

   Expression(const Expression& other)
      :_expression(other._expression)
   { }

   int Equal()
   {
      StackClear();
      // std::cout << "stack clear done..." << std::endl; // for debug
      for (auto ch : _expression)
      {
	 if (isdigit(ch)) {
	    _numSt.push(ch - '0');
	 }
	 else
	 {
	    // + - * / % ( )
	    if (ch == ' ') { continue; }
	    if (ch == '(' ||  _operSt.empty() || _operMap[ch] > _operMap[_operSt.top()]) {
	       _operSt.push(ch);
	    }
	    else if (ch == ')')
	    {
	       while (_operSt.top() != '(') {
		  DoCalculate();
	       }
	       _operSt.pop(); // pop '('
	    }
	    else // _operMap[ch] <= _operMap[_operSt.top()]
	    {  
	       while (_operMap[ch] <= _operMap[_operSt.top()]) {
		  DoCalculate();
	       }
	       _operSt.push(ch);
	    }
	 }
      }
      while (!_operSt.empty()) {
	 DoCalculate();
      }
      return _numSt.top();
   }

private:
   void StackClear()
   {
      std::stack<int> tmpNumSt;
      std::stack<char> tmpOperSt;
      _numSt.swap(tmpNumSt);
      _operSt.swap(tmpOperSt);
   }

   void DoCalculate()
   {
      int rightNum = _numSt.top();
      _numSt.pop();
      int leftNum = _numSt.top();
      _numSt.pop();
      char oper = _operSt.top();
      _operSt.pop();
      std::cout << "leftNum: " << leftNum << ", rightNum: " << rightNum << ", oper: " << oper << std::endl;
      int res = _operHandlerMap[oper](leftNum, rightNum);
      _numSt.push(res);
   }

private:
   static std::unordered_map<char, const int> _operMap; 
   static std::unordered_map<char, std::function<int(int, int)>> _operHandlerMap;

private:
   std::string _expression;
   std::stack<int> _numSt;
   std::stack<char> _operSt;
};

std::unordered_map<char, const int> Expression::_operMap {
      { '+', 1 }, { '-', 1 },
      { '*', 2 }, { '/',2 }, { '%', 2 }
};

std::unordered_map<char, std::function<int(int, int)>> Expression::_operHandlerMap {
      { '+', [](int x, int y) { return x + y; } },
      { '-', [](int x, int y) { return x - y; } },
      { '*', [](int x, int y) { return x * y; } },
      { '/', [](int x, int y) { return x / y; } },
      { '%', [](int x, int y) { return x % y; } }
};


